package com.dart.sys.service.impl;

import java.util.Enumeration;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.JmsException;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

import com.dart.commons.constants.DestinationConst;
import com.dart.framework.aop.LogHandler;
import com.dart.framework.common.IpHelper;
import com.dart.framework.common.util.HttpUtil;
import com.dart.framework.exception.AppException;
import com.dart.framework.exception.LogException;
import com.dart.framework.spring.SpringHelper;
import com.dart.sys.entity.SysExLog;
import com.dart.sys.entity.SysOperateLog;
import com.dart.sys.service.SysExLogService;
import com.dart.sys.service.SysOperateLogService;

public class LogHandelerServiceImpl implements LogHandler {
	
	private static final Logger logger = LoggerFactory.getLogger(LogHandelerServiceImpl.class) ;

	private static final String LOG_OPERATE = "[类名]:%s, [方法]:%s, [参数]:%s, [IP]:%s";
	private static final String LOG_EXCEPTION = "[类名]:%s, [方法]:%s, [参数]:%s, [异常]:%s, [IP]:%s";

	@Autowired
	private SysOperateLogService operateLogService ;
	
	@Autowired
	private SysExLogService exLogService ;
	
	@Autowired
	@Qualifier("jmsQueueTemplate")
	private JmsTemplate jmsTemplate ;
	
	@Override
	public void saveLog(final ProceedingJoinPoint joinPoint, String methodName, String operate) throws LogException {
		HttpServletRequest request = SpringHelper.getHttpServletRequest();
		
		String className = joinPoint.getTarget().getClass().getName();
		Object[] params = joinPoint.getArgs();
		String ip = "非WEB访问";
		if (null != request) {
			ip = IpHelper.getIpAddr(request);
		}
		String currentLongURL = HttpUtil.getCurrentLongURL(request, true) ;
		String paramsStr = appendParams(params, request) ;
		String detail = String.format(LOG_OPERATE, className, methodName, paramsStr, ip);
		
		
		final SysOperateLog entity = new SysOperateLog() ;
		entity.setOperate(operate);
		entity.setClassName(className);
		entity.setMethodName(methodName);
		entity.setUrl(currentLongURL);
		entity.setParams(paramsStr);
		entity.setIp(ip);
		entity.setDetail(detail);
		
		try {
			//发送JMS消息
			this.jmsTemplate.send(DestinationConst.SYS_OPERATE_LOG, new MessageCreator() {
				@Override
				public Message createMessage(Session session) throws JMSException {
					ObjectMessage message = session.createObjectMessage();
					message.setObject(entity);
					return message;
				}
			});
		} catch (JmsException e) {
			logger.error("JMS消息异常，非JMS记录用户操作：" + e);
			logger.info("用户操作记录，操作说明：{}, 类名：{}, 方法：{}, 参数：{}, IP：{}, 详情：{}", operate, className, methodName, paramsStr, ip, detail);
			
			this.operateLogService.insertLog(entity);
		}
	}

	@Override
	public void thorwingLog(JoinPoint joinPoint, String methodName, Throwable ex, String operate) throws LogException {
		HttpServletRequest request = SpringHelper.getHttpServletRequest();

		String className = joinPoint.getTarget().getClass().getName();
		Object[] params = joinPoint.getArgs();
		String ip = "非WEB访问";
		if (null != request) {
			ip = IpHelper.getIpAddr(request);
		}
		String currentLongURL = HttpUtil.getCurrentLongURL(request, true) ;
		String paramsStr = appendParams(params, request) ;
		String detail = String.format(LOG_EXCEPTION, className, methodName, paramsStr, ex, ip) ;
		
		final SysExLog entity = new SysExLog() ;
		entity.setOperate(operate);
		entity.setClassName(className);
		entity.setMethodName(methodName);
		entity.setUrl(currentLongURL);
		entity.setParams(paramsStr);
		entity.setException(AppException.getStackTrace(ex));
		entity.setIp(ip);
		entity.setDetail(detail);
		
		try {
			//发送JMS消息
			this.jmsTemplate.send(DestinationConst.SYS_EX_LOG, new MessageCreator() {
				@Override
				public Message createMessage(Session session) throws JMSException {
					ObjectMessage message = session.createObjectMessage();
					message.setObject(entity);
					return message;
				}
			});
		} catch (JmsException e) {
			logger.error("JMS消息异常，非JMS记录用户操作异常：" + e);
			logger.error("用户操作异常，操作说明：{},操作详情：{}\r\n异常详情：{}", operate, detail, AppException.getStackTrace(ex));
			
			this.exLogService.insertLog(entity);
		}
		

	}


	/**
	 * 参数解析和拼装
	 * 
	 * @param params
	 *            形参
	 * @param request
	 *            HttpServletRequest 参数
	 * @return
	 */
	private String appendParams(Object[] params, HttpServletRequest request) {
		StringBuffer strBuf = new StringBuffer();

		if (null != request) {
			if (params != null && params.length > 0) {
				Enumeration<String> paraNames = request.getParameterNames();

				while (paraNames.hasMoreElements()) {
					String key = paraNames.nextElement();
					strBuf.append(key).append("=");
					strBuf.append(request.getParameter(key)).append("&");
				}
				if (strBuf.length() > 0 && StringUtils.isBlank(strBuf.toString())) {
					strBuf.append(request.getQueryString());
				}
			}
		}

		/*for(int i=0;i<params.length;i++){
			if(null != params[i]) {
				String objParamJson = JSON.toJSON(params[i].toString()).toString().replaceAll("\\[\\{", "").replaceAll("\\}\\]", "");
				if (null != objParamJson && objParamJson.length() > 0) {
					String[] split = objParamJson.split(",");
					for (String param : split) {
						strBuf.append(param.replaceAll("\"", "").replaceAll(":", "=")).append("&");
					}
				}
			}
			//System.out.println(strBuf.toString());
            //System.out.println("\t==>参数["+i+"]:\t"+params[i].toString());
        }*/

		if (strBuf.lastIndexOf("&") != -1) {
			strBuf.deleteCharAt(strBuf.length() - 1);
		}
		if (StringUtils.isBlank(strBuf)) {
			strBuf.append("无");
		}

		return strBuf.toString();
	}

}
